#pragma once
#include "torus.h"
#include <iostream>
#include "MyVertex.h"

namespace CAD_CAM
{
	Torus::Torus(int vertices, int stripes, double smallRadius, double bigRadius): Primitive(vertices*stripes, vertices*stripes*4),
		numVertices(vertices), numStripes(stripes),
		r(smallRadius), R(bigRadius)
	{
		buildTorus(verticesArray, indicesArray);
	}

	Torus::~Torus()
	{
	}

	void Torus::DrawShader(QGLShaderProgram& shaderProgram, QMatrix4x4& viewMatrix, QMatrix4x4& projectionMatrix)
	{
		if(isInited == false)
			initBuffers();
		mVertexVBO.bind();
		mIndexVBO.bind();
	
		QMatrix4x4 modelMatrix;
		//mModelMatrix.translate(translation);
		//mModelMatrix *= rotationMatrix;
		modelMatrix.scale(sizeScale);

		shaderProgram.bind();

		int inPositionLocation = shaderProgram.attributeLocation("inPosition");
		int inColorLocation = shaderProgram.attributeLocation("inColor");
		int inModelMatrixLocation = shaderProgram.uniformLocation("inModelMatrix");
		int inViewMatrixLocation = shaderProgram.uniformLocation("inViewMatrix");
		int inProjectionMatrixLocation = shaderProgram.uniformLocation("inProjectionMatrix");

		shaderProgram.enableAttributeArray(inPositionLocation);
		shaderProgram.enableAttributeArray(inColorLocation);

		shaderProgram.setAttributeBuffer(inPositionLocation, GL_FLOAT, 0, 3, sizeof(MyVertex));
		shaderProgram.setAttributeBuffer(inColorLocation, GL_FLOAT, 12, 3, sizeof(MyVertex));
		shaderProgram.setUniformValue(inModelMatrixLocation, modelMatrix);
		shaderProgram.setUniformValue(inViewMatrixLocation, viewMatrix);
		shaderProgram.setUniformValue(inProjectionMatrixLocation, projectionMatrix);

		glDrawElements(GL_LINES, indices, GL_UNSIGNED_INT, 0);

		shaderProgram.disableAttributeArray(inPositionLocation);
		shaderProgram.disableAttributeArray(inColorLocation);
	
		shaderProgram.release();
	
		mVertexVBO.release();
		mIndexVBO.release();
	}

	void Torus::buildTorus(MyVertex* verticesArray, QVector<GLuint> & indicesArray)
	{
		float u = 0.0f, v = 0.0f, twoPi = 2 * M_PI;
		float uStep = twoPi / numStripes;
		float vStep = twoPi / numVertices;
		float ringRadius = (R - r)/ 2.0f;
		float torusRadius = r + ringRadius;

		for(int i=0; i<numVertices; ++i)
		{
			u = 0.0f;
			for(int j=0; j<numStripes; ++j)
			{
				int offset = i*numStripes+j;
				int offset4 = offset * 4;
				float x = (torusRadius + ringRadius * cosf(u)) * cosf(v);
				float y = (torusRadius + ringRadius * cosf(u)) * sinf(v);
				float z= ringRadius * sinf(u);

				verticesArray[offset] = MyVertex((torusRadius + ringRadius * cosf(u)) * cosf(v),
					(torusRadius + ringRadius * cosf(u)) * sinf(v),
					ringRadius * sinf(u), 
					//(float)offset / verticesCount, u / twoPi, 0.0f);
					1.0, 0.0, 0.0);
				indicesArray.append(offset);

				indicesArray.append((offset+1) % numStripes == 0 ? (offset+1 - numStripes) : offset+1);
				indicesArray.append(offset);
				indicesArray.append((offset + numStripes) % vertices);
				u += uStep;			
			}
			v += vStep;
		}
	}

	//void Torus::rotate(float angle, QVector3D vector)
	//{
	//	rotationMatrix.rotate(angle, vector);
	//}
	//
	//void Torus::rotate(float angle, float x, float y, float z)
	//{
	//	rotationMatrix.rotate(angle, x, y, z);
	//}
	//
	//void Torus::translate(QVector3D vector)
	//{
	//	translation += vector;
	//}
	//
	//void Torus::translate(float x, float y, float z)
	//{
	//	translation += QVector3D(x, y, z);
	//}
	//
	//void Torus::scale(QVector3D scale)
	//{
	//	sizeScale *= scale;
	//}
	//void Torus::setSize(QVector3D size)
	//{
	//	sizeScale = size;
	//}
	//
	void Torus::setWidth(double width)
	{
		sizeScale.setX(width);
	}

	void Torus::setHeight(double height)
	{
		sizeScale.setY(height);
	}

	void Torus::setLength(double length)
	{
		sizeScale.setZ(length);
	}

	void Torus::setBigRadius(float bigRadius)
	{
		R = bigRadius;
		mVertexVBO.bind();
		MyVertex* vertices = (MyVertex*)mVertexVBO.map(QGLBuffer::ReadWrite);
		buildTorus(vertices, indicesArray);
		mVertexVBO.unmap();
		mVertexVBO.release();
	}

	void Torus::setSmallRadius(float smallRadius)
	{
		r = smallRadius;
		mVertexVBO.bind();
		MyVertex* vertices = (MyVertex*)mVertexVBO.map(QGLBuffer::ReadWrite);
		buildTorus(vertices, indicesArray);
		mVertexVBO.unmap();
		mVertexVBO.release();
	}
}